<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>水印添加器</title>
  <!-- 引入样式 -->
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css" />
  <!-- 引入 Vue -->
  <script src="https://unpkg.com/vue@next"></script>
  <!-- 引入组件库 -->
  <script src="https://unpkg.com/element-plus"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .title {
      font-size: 20px;
      margin: 30px;
      color: #888;
    }

    canvas {
      background-color: #ccc;
      max-width: 960px;
    }

    .cavasimg {
      width: 230px;
      height: 50px;
      background-color: #409EFF;
      border-radius: 5px;
      cursor: pointer;
    }

    .mycontainer {
      width: 960px;
      text-align: center;
      margin: 0 auto;
      padding-bottom: 20px;
    }

    .textstyle {
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .selectbox {
      display: flex;
      margin-top: 20px;
      justify-content: space-between;
    }

    .box {
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
      flex: 1;
      color: #409EFF;
    }

    li {
      list-style: none;
    }

    .btns {
      display: flex;
      justify-content: space-between;
      margin-left: 20px;
    }

    .btns button {
      width: 120px;
      height: 50px;
      margin-right: 30px;
      border-radius: 10px;
      background-color: #409EFF;
      color: #fff;
      outline: none;
      border: none;
    }

    .colorselect {
      border-radius: 5px;
      width: 80px;
      height: 40px;
      outline: none;
      border: none;
    }

    .canvastext {
      height: 40px;
      width: 150px;
      border-radius: 5px;
      text-indent: 10px;
      border: 1px solid #409EFF;
      border: none;
      outline: none;
    }

    .centerselect {
      margin: 20 0;
      display: flex;
      justify-content: space-between;
      color: #409EFF;
    }

    .centerselect li {
      height: 50px;
      line-height: 50px;
    }

    span {
      display: inline-block;
    }

    .smallprant {
      position: relative;
    }

    html,
    body {
      user-select: none;
    }

    .block {
      width: 150px;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="mycontainer">
      <div class="title">水印添加器小工具</div>
      <canvas id="canvasImg" :class="!imgnode ? 'cavasimg' : ''" @click="uploadfile()"></canvas>
      <div class="selectbox" v-show="imgnode">
        <div class="textstyle">
          <div style="color:#409EFF">水印文字:<input type="text" class="canvastext" @input="addtext" v-model="inputval"
              placeholder="请输入水印文字" /></div>
          <div style="color:#409EFF;display: flex;align-items: center;">水印颜色：<input type="color" class="colorselect"
              placeholder="" v-model="color" @change="loop"></div>
          <el-button type="primary" @click="addlogo">上传水印或logo图</el-button>
          <el-button type="primary" @click="unset">重新设置水印</el-button>
          <el-button type="primary" @click="saveimg">下载图片</el-button>
        </div>
      </div>
      <div v-show="imgnode">
        <ul class="centerselect">
          <li>位置&nbsp;&nbsp;
            <el-select v-model="position" placeholder="请选择" @change="loop">
              <el-option label="中心" value="中心"></el-option>
              <el-option label="左上" value="左上"></el-option>
              <el-option label="上" value="上"></el-option>
              <el-option label="右上" value="右上"></el-option>
              <el-option label="右" value="右"></el-option>
              <el-option label="右下" value="右下"></el-option>
              <el-option label="下" value="下"></el-option>
              <el-option label="左下" value="左下"></el-option>
              <el-option label="左" value="左"></el-option>
            </el-select>
          </li>
          <li class="rotate">旋转&nbsp;&nbsp;
            <el-select v-model="rotate" placeholder="请选择" @change="loop">
              <el-option label="0°" :value="0"></el-option>
              <el-option label="15°" :value="15"></el-option>
              <el-option label="30°" :value="30"></el-option>
              <el-option label="45°" :value="45"></el-option>
              <el-option label="60°" :value="60"></el-option>
            </el-select>
          </li>
          <li>重复&nbsp;&nbsp;
            <el-select v-model="repetition" placeholder="请选择" @change="loop">
              <el-option label="不重复" :value="false"></el-option>
              <el-option label="重复" :value="true"></el-option>
            </el-select>
          </li>
        </ul>
      </div>
      <div v-show="imgnode" class="box">
        <span>x间距</span>
        <div class="block" style="margin:10px 0 0 0;">
          <el-slider v-model="value0" :step="1" :max="slidermax" @input="loop"></el-slider>
        </div>
        <span>y间距</span>
        <div class="block" style="margin:10px 0 0 0;">
          <el-slider v-model="value1" :step="1" :max="slidermax" @input="loop"></el-slider>
        </div>
        <span>大小</span>
        <div class="block" style="margin:10px 0;">
          <el-slider v-model="value2" :step="1" :max="slidermax" @input="loop"></el-slider>
        </div>
        <span>透明度</span>
        <div class="block" style="margin:10px 0;">
          <el-slider v-model="value3" :step="0.1" :max='1' @input="loop"></el-slider>
        </div>
      </div>
    </div>
  </div>
  <script>
    const App = {
      data() {
        return {
          value0: 10, // x方向间据
          value1: 10, // y方向间据
          value2: 90,
          value3: 0.3,
          imgnode: null,
          inputval: null,
          color: '#409EFF',
          position: '中心',
          rotate: 15, //旋转角度
          repetition: false, //不重复
          logo: null,
          slidermax: 100
        }
      },
      mounted() {
        let canvas = document.getElementById('canvasImg')
        let contain = document.getElementsByClassName('mycontainer')[0]
        canvas.width = 960
        canvas.height = 320
        let context = canvas.getContext('2d')
        context.font = this.value2 + "px '宋体'"
        context.fillStyle = '#fff'
        context.save()
        context.globalAlpha = 1
        context.rotate(0)
        context.translate(0, 0)
        context.fillText('请选择添加水印的图片', 45, canvas.height / 1.6)
        context.restore()
      },
      methods: {
        loop() {
          this.clear()
          if (this.imgnode) this.drawimg(this.imgnode)
          if (this.inputval) this.drawtext(this.inputval)
          if (this.logo) this.drawlogo(this.logo)
        },
        //添加文本水印
        addtext(e) {
          this.inputval = e.target.value
          this.loop();
        },
        //选择需要加水印的图
        uploadfile(e) {
          let input = document.createElement('input')
          input.type = 'file'
          input.onchange = () => {
            let url = URL.createObjectURL(input.files[0])
            let img = this.loadImg(url)
            img.onload = () => {
              URL.revokeObjectURL(url)
              let canvas = document.getElementById('canvasImg')
              canvas.width = img.naturalWidth
              canvas.height = img.naturalHeight
              let max = canvas.width < canvas.height ? canvas.height : canvas.width
              this.slidermax = Math.ceil(max / 3)
              this.imgnode = img
              this.loop()
            }
          }
          let event = document.createEvent('MouseEvents');
          event.initEvent("click", true, false);
          input.dispatchEvent(event);
        },
        addlogo() {
          let input = document.createElement('input')
          input.type = 'file'
          input.onchange = () => {
            let url = URL.createObjectURL(input.files[0])
            let img = this.loadImg(url)
            this.logo = img
            img.onload = () => {
              URL.revokeObjectURL(url)
              this.loop();
            }
          }
          let event = document.createEvent('MouseEvents');
          event.initEvent("click", true, false);
          input.dispatchEvent(event);
        },
        //绘制图片
        drawimg(url) {
          let canvas = document.getElementById('canvasImg')
          let context = canvas.getContext('2d')
          context.drawImage(url, 0, 0)
        },
        //绘制logo
        drawlogo(img) {
          let canvas = document.getElementById('canvasImg')
          let context = canvas.getContext('2d')
          let strarr = this.setposition()
          if (!this.repetition) {
            context.save()
            context.globalAlpha = this.value3
            context.translate(strarr[0], strarr[1])
            context.rotate((Math.PI / 180) * (this.rotate * 1))
            context.translate(-strarr[0], -strarr[1])
            context.drawImage(img || this.logo, strarr[0], strarr[1])
            context.restore()
          } else {
            for (let i = 0; i < canvas.width; i += (this.value2 * 1 + this.value0 * 1)) {
              for (let j = 0; j < canvas.height; j += (this.value2 * 1 + this.value1 * 1)) {
                context.save()
                context.globalAlpha = this.value3
                context.translate(strarr[0] + i, strarr[1] + j)
                context.rotate((Math.PI / 180) * (this.rotate * 1))
                context.translate(-strarr[0] - i, -strarr[1] - j)
                context.drawImage(img || this.logo, strarr[0] + i, strarr[1] + j)
                context.restore()
              }
            }
          }
        },
        setposition() {
          let canvas = document.getElementById('canvasImg')
          let strarr = []
          switch (this.position) {
            case '中心':
              strarr = [canvas.width / 2, canvas.height / 2];
              break;
            case '左上':
              strarr = [0, 0];
              break;
            case '上':
              strarr = [canvas.width / 2, 0];
              break;
            case '右上':
              strarr = [canvas.width, 0];
              break;
            case '右':
              strarr = [canvas.width, canvas.height / 2];
              break;
            case '右下':
              strarr = [canvas.width, canvas.height];
              break;
            case '下':
              strarr = [canvas.width / 2, canvas.height];
              break;
            case '左下':
              strarr = [0, canvas.height];
              break;
            case '左':
              strarr = [0, canvas.height / 2];
              break;
          }
          //调整位置
          if (strarr[1] == canvas.height) {
            strarr[1] = canvas.height - this.value2
          }
          if (strarr[1] == canvas.height / 2) {
            strarr[1] = (canvas.height / 2) - this.value2 / 2
          }
          if (strarr[0] == canvas.width / 2) {
            strarr[0] = (canvas.width / 2) - this.value2 / 2
          }
          if (strarr[0] == canvas.width) {
            strarr[0] = canvas.width - this.value2
          }
          //----调整位置END----
          return strarr
        },
        //绘制字体水印
        drawtext(value) {
          let canvas = document.getElementById('canvasImg')
          let context = canvas.getContext('2d')
          let strarr = this.setposition()
          context.font = this.value2 + "px '宋体'"
          context.fillStyle = this.color
          if (!this.repetition) {
            context.save()
            context.globalAlpha = this.value3
            context.translate(strarr[0], strarr[1])
            context.rotate((Math.PI / 180) * (this.rotate * 1))
            context.translate(-strarr[0], -strarr[1])
            context.fillText(value, strarr[0], strarr[1] + this.value2)
            context.restore()
          } else {
            for (let i = 0; i < canvas.width; i += (this.value2 * this.inputval.length + this.value0)) {
              for (let j = 0; j < canvas.height; j += (this.value2 + this.value1)) {
                context.save()
                context.globalAlpha = this.value3
                context.translate(strarr[0] + i, strarr[1] + j)
                context.rotate((Math.PI / 180) * (this.rotate * 1))
                context.translate(-strarr[0] - i, -strarr[1] - j)
                context.fillText(value, (strarr[0]) + i, (strarr[1]) + j + this.value2)
                context.restore()
              }
            }
          }
        },
        //保存图片到本地
        saveimg() {
          let canvas = document.getElementById('canvasImg')
          canvas.toBlob(blob => {
            let url = URL.createObjectURL(blob)
            let save_link = document.createElement('a');
            save_link.href = url;
            save_link.download = new Date().getTime() + '.png';
            let event = document.createEvent('MouseEvents');
            event.initEvent("click", true, false);
            save_link.dispatchEvent(event);
            setTimeout(() => {
              URL.revokeObjectURL(url)
            }, 5000);
          })
        },
        //重新设置
        unset() {
          this.inputval = null
          this.logo = null
          this.loop()
        },
        //----功能函数----
        loadImg(url) {
          const img = document.createElement('img')
          img.src = url
          return img
        },
        clear() {
          let canvas = document.getElementById('canvasImg')
          let context = canvas.getContext('2d')
          context.clearRect(0, 0, canvas.width, canvas.height)
        }
        //----功能函数END----
      }
    }
    const app = Vue.createApp(App);
    app.use(ElementPlus);
    app.mount("#app");
  </script>
</body>

</html>